/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "Frustrum.h"

namespace liba
{
namespace math
{

Frustrum::Frustrum( const float & near_plane, const float & far_plane,
				 const float & fov_horizontal, const float & fov_vertical )
{
    spaces[NEAR_PLANE] = HalfSpace( Plane(Vector3<float>(0,0,1), near_plane) );
    // -farPlane, because normal points to viewer
    spaces[FAR_PLANE] = HalfSpace( Plane(Vector3<float>(0,0,-1), -far_plane) );
    
    float ch = float( cos( fov_horizontal/2 ) );
    float sh = float( sin( fov_horizontal/2 ) );
    spaces[LEFT_PLANE] = HalfSpace( Plane(Vector3<float>(ch,0,sh), 0) );
    spaces[RIGHT_PLANE] = HalfSpace( Plane(Vector3<float>(-ch,0,sh), 0) );

    float cv = float( cos( fov_vertical/2 ) );
    float sv = float( sin( fov_vertical/2 ) );
    spaces[TOP_PLANE] = HalfSpace( Plane(Vector3<float>(0,-cv,sv), 0) );
    spaces[BOTTOM_PLANE] = HalfSpace( Plane(Vector3<float>(0,cv,sv), 0) );
}

Frustrum::Frustrum( const float & near_plane, const float & far_plane,
	const float & left_plane, const float & right_plane,
	const float & top_plane, const float & bottom_plane )
{
    spaces[NEAR_PLANE] = HalfSpace( Plane(Vector3<float>(0,0,1), near_plane) );
    // -farPlane, because normal points to viewer
    spaces[FAR_PLANE] = HalfSpace( Plane(Vector3<float>(0,0,-1), -far_plane) );
    
    spaces[LEFT_PLANE] = HalfSpace( Plane(Vector3<float>(1,0,0), left_plane) );
    spaces[RIGHT_PLANE] = HalfSpace( Plane(Vector3<float>(-1,0,0), -right_plane) );

    spaces[TOP_PLANE] = HalfSpace( Plane(Vector3<float>(0,-1,0), top_plane) );
    spaces[BOTTOM_PLANE] = HalfSpace( Plane(Vector3<float>(0,1,0), -bottom_plane) );
}

Intersect::Type Frustrum::intersects(const Sphere & sphere)const
{
    Intersect::Type ret( Intersect::CONTAINS );
    Intersect::Type temp;
    for( int i = 0; i < 6 && ret < Intersect::DISJOINT; ++i )
    {
        temp = spaces[i].intersects( sphere );
        if( temp > Intersect::CONTAINS )
            ret = temp;
    }

    return ret;
}

Intersect::Type Frustrum::intersects( const Box & box )const
{
    Intersect::Type ret( Intersect::CONTAINS );
    Intersect::Type temp;
    for( int i = 0; i < 6 && ret < Intersect::DISJOINT; ++i )
    {
        temp = spaces[i].intersects( box );
        if( temp > Intersect::CONTAINS )
            ret = temp;
    }

    return ret;
}

} // namespace math
} // namespace liba

